//308
        private static char[][] sectionalTermMap = {
                        { 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5,
                                        5, 5, 5, 4, 5, 5 },
                        { 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3,
                                        3, 4, 4, 3, 3, 3 },
                        { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,
                                        5, 5, 4, 5, 5, 5, 5 },
                        { 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4,
                                        4, 5, 4, 4, 4, 4, 5 },
                        { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,
                                        5, 5, 4, 5, 5, 5, 5 },
                        { 6, 6, 7, 7, 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5,
                                        5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5 },
                        { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,
                                        7, 7, 6, 6, 6, 7, 7 },
                        { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,
                                        7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7 },
                        { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,
                                        7, 7, 6, 7, 7, 7, 7 },
                        { 9, 9, 9, 9, 8, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 9, 8, 8, 8, 8, 7, 8,
                                        8, 8, 7, 7, 8, 8, 8 },
                        { 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7,
                                        7, 7, 6, 6, 7, 7, 7 },
                        { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,
                                        7, 7, 6, 6, 6, 7, 7 } };
        private static char[][] sectionalTermYear = {
                        { 13, 49, 85, 117, 149, 185, 201, 250, 250 },
                        { 13, 45, 81, 117, 149, 185, 201, 250, 250 },
                        { 13, 48, 84, 112, 148, 184, 200, 201, 250 },
                        { 13, 45, 76, 108, 140, 172, 200, 201, 250 },
                        { 13, 44, 72, 104, 132, 168, 200, 201, 250 },
                        { 5, 33, 68, 96, 124, 152, 188, 200, 201 },
                        { 29, 57, 85, 120, 148, 176, 200, 201, 250 },
                        { 13, 48, 76, 104, 132, 168, 196, 200, 201 },
                        { 25, 60, 88, 120, 148, 184, 200, 201, 250 },
                        { 16, 44, 76, 108, 144, 172, 200, 201, 250 },
                        { 28, 60, 92, 124, 160, 192, 200, 201, 250 },
                        { 17, 53, 85, 124, 156, 188, 200, 201, 250 } };
        private static char[][] principleTermMap = {
                        { 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20,
                                        20, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20 },
                        { 20, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19,
                                        19, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18 },
                        { 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21,
                                        20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 20 },
                        { 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20,
                                        19, 20, 20, 20, 19, 19, 20, 20, 19, 19, 19, 20, 20 },
                        { 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21,
                                        20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 21 },
                        { 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22,
                                        21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 21 },
                        { 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23,
                                        22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 23 },
                        { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,
                                        22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },
                        { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,
                                        22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },
                        { 24, 24, 24, 24, 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24,
                                        23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 23 },
                        { 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23,
                                        22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 22 },
                        { 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22,
                                        21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 22 } };
        private static char[][] principleTermYear = {
                        { 13, 45, 81, 113, 149, 185, 201 },
                        { 21, 57, 93, 125, 161, 193, 201 },
                        { 21, 56, 88, 120, 152, 188, 200, 201 },
                        { 21, 49, 81, 116, 144, 176, 200, 201 },
                        { 17, 49, 77, 112, 140, 168, 200, 201 },
                        { 28, 60, 88, 116, 148, 180, 200, 201 },
                        { 25, 53, 84, 112, 144, 172, 200, 201 },
                        { 29, 57, 89, 120, 148, 180, 200, 201 },
                        { 17, 45, 73, 108, 140, 168, 200, 201 },
                        { 28, 60, 92, 124, 160, 192, 200, 201 },
                        { 16, 44, 80, 112, 148, 180, 200, 201 },
                        { 17, 53, 88, 120, 156, 188, 200, 201 } };


        public int computeSolarTerms() {
                if (gregorianYear < 1901 || gregorianYear > 2100)
                        return 1;
                sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);
                principleTerm = principleTerm(gregorianYear, gregorianMonth);
                return 0;
        }


        public static int sectionalTerm(int y, int m) {
                if (y < 1901 || y > 2100)
                        return 0;
                int index = 0;
                int ry = y - baseYear + 1;
                while (ry >= sectionalTermYear[m - 1][index])
                        index++;
                int term = sectionalTermMap[m - 1][4 * index + ry % 4];
                if ((ry == 121) && (m == 4))
                        term = 5;
                if ((ry == 132) && (m == 4))
                        term = 5;
                if ((ry == 194) && (m == 6))
                        term = 6;
                return term;
        }


        public static int principleTerm(int y, int m) {
                if (y < 1901 || y > 2100)
                        return 0;
                int index = 0;
                int ry = y - baseYear + 1;
                while (ry >= principleTermYear[m - 1][index])
                        index++;
                int term = principleTermMap[m - 1][4 * index + ry % 4];
                if ((ry == 171) && (m == 3))
                        term = 21;
                if ((ry == 181) && (m == 5))
                        term = 21;
                return term;
        }


        public String toString() {
                StringBuffer buf = new StringBuffer();
                buf.append("Gregorian Year: " + gregorianYear + "\n");
                buf.append("Gregorian Month: " + gregorianMonth + "\n");
                buf.append("Gregorian Date: " + gregorianDate + "\n");
                buf.append("Is Leap Year: " + isGregorianLeap + "\n");
                buf.append("Day of Year: " + dayOfYear + "\n");
                buf.append("Day of Week: " + dayOfWeek + "\n");
                buf.append("Chinese Year: " + chineseYear + "\n");
                buf.append("Heavenly Stem: " + ((chineseYear - 1) % 10) + "\n");
                buf.append("Earthly Branch: " + ((chineseYear - 1) % 12) + "\n");
                buf.append("Chinese Month: " + chineseMonth + "\n");
                buf.append("Chinese Date: " + chineseDate + "\n");
                buf.append("Sectional Term: " + sectionalTerm + "\n");
                buf.append("Principle Term: " + principleTerm + "\n");
                return buf.toString();
        }


        public String[] getYearTable() {
                setGregorian(gregorianYear, 1, 1);
                computeChineseFields();
                computeSolarTerms();
                String[] table = new String[58]; // 6*9 + 4
                table[0] = getTextLine(27, "公历年历：" + gregorianYear);
                table[1] = getTextLine(27, "农历年历：" + (chineseYear + 1) + " ("
                                + stemNames[(chineseYear + 1 - 1) % 10]
                                + branchNames[(chineseYear + 1 - 1) % 12] + " - "
                                + animalNames[(chineseYear + 1 - 1) % 12] + "年)");
                int ln = 2;
                String blank = "                                         " + "  "
                                + "                                         ";
                String[] mLeft = null;
                String[] mRight = null;
                for (int i = 1; i <= 6; i++) {
                        table[ln] = blank;
                        ln++;
                        mLeft = getMonthTable();
                        mRight = getMonthTable();
                        for (int j = 0; j < mLeft.length; j++) {
                                String line = mLeft[j] + "  " + mRight[j];
                                table[ln] = line;
                                ln++;
                        }
                }
                table[ln] = blank;
                ln++;
                table[ln] = getTextLine(0, "##/## - 公历日期/农历日期，(*)#月 - (闰)农历月第一天");
                ln++;
                return table;
        }


        public static String getTextLine(int s, String t) {
                String str = "                                         " + "  "
                                + "                                         ";
                if (t != null && s < str.length() && s + t.length() < str.length())
                        str = str.substring(0, s) + t + str.substring(s + t.length());
                return str;
        }


        private static String[] monthNames = { "一", "二", "三", "四", "五", "六", "七",
                        "八", "九", "十", "十一", "十二" };


        public String[] getMonthTable() {
                setGregorian(gregorianYear, gregorianMonth, 1);
                computeChineseFields();
                computeSolarTerms();
                String[] table = new String[8];
                String title = null;
                if (gregorianMonth < 11)
                        title = "                   ";
                else
                        title = "                 ";
                title = title + monthNames[gregorianMonth - 1] + "月"
                                + "                   ";
                String header = "   日    一    二    三    四    五    六 ";
                String blank = "                                          ";
                table[0] = title;
                table[1] = header;
                int wk = 2;
                String line = "";
                for (int i = 1; i < dayOfWeek; i++) {
                        line += "     " + ' ';
                }
                int days = daysInGregorianMonth(gregorianYear, gregorianMonth);
                for (int i = gregorianDate; i <= days; i++) {
                        line += getDateString() + ' ';
                        rollUpOneDay();
                        if (dayOfWeek == 1) {
                                table[wk] = line;
                                line = "";
                                wk++;
                        }
                }
                for (int i = dayOfWeek; i <= 7; i++) {
                        line += "     " + ' ';
                }
                table[wk] = line;
                for (int i = wk + 1; i < table.length; i++) {
                        table[i] = blank;
                }
                for (int i = 0; i < table.length; i++) {
                        table[i] = table[i].substring(0, table[i].length() - 1);
                }


                return table;
        }


        private static String[] chineseMonthNames = { "正", "二", "三", "四", "五", "六",
                        "七", "八", "九", "十", "冬", "腊" };
        private static String[] principleTermNames = { "雨水", "春分", "谷雨", "夏满",
                        "夏至", "大暑", "处暑", "秋分", "霜降", "小雪", "冬至", "大寒" };
        private static String[] sectionalTermNames = { "立春", "惊蛰", "清明", "立夏",
                        "芒种", "小暑", "立秋", "白露", "寒露", "立冬", "大雪", "小寒" };


        public String getDateString() {
                String str = "*  /  ";
                String gm = String.valueOf(gregorianMonth);
                if (gm.length() == 1)
                        gm = ' ' + gm;
                String cm = String.valueOf(Math.abs(chineseMonth));
                if (cm.length() == 1)
                        cm = ' ' + cm;
                String gd = String.valueOf(gregorianDate);
                if (gd.length() == 1)
                        gd = ' ' + gd;
                String cd = String.valueOf(chineseDate);
                if (cd.length() == 1)
                        cd = ' ' + cd;
                if (gregorianDate == sectionalTerm) {
                        str = " " + sectionalTermNames[gregorianMonth - 1];
                } else if (gregorianDate == principleTerm) {
                        str = " " + principleTermNames[gregorianMonth - 1];
                } else if (chineseDate == 1 && chineseMonth > 0) {
                        str = " " + chineseMonthNames[chineseMonth - 1] + "月";
                } else if (chineseDate == 1 && chineseMonth < 0) {
                        str = "*" + chineseMonthNames[-chineseMonth - 1] + "月";
                } else {
                        str = gd + '/' + cd;
                }
                return str;
        }


        public int rollUpOneDay() {
                dayOfWeek = dayOfWeek % 7 + 1;
                dayOfYear++;
                gregorianDate++;
                int days = daysInGregorianMonth(gregorianYear, gregorianMonth);
                if (gregorianDate > days) {
                        gregorianDate = 1;
                        gregorianMonth++;
                        if (gregorianMonth > 12) {
                                gregorianMonth = 1;
                                gregorianYear++;
                                dayOfYear = 1;
                                isGregorianLeap = isGregorianLeapYear(gregorianYear);
                        }
                        sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);
                        principleTerm = principleTerm(gregorianYear, gregorianMonth);
                }
                chineseDate++;
                days = daysInChineseMonth(chineseYear, chineseMonth);
                if (chineseDate > days) {
                        chineseDate = 1;
                        chineseMonth = nextChineseMonth(chineseYear, chineseMonth);
                        if (chineseMonth == 1)
                                chineseYear++;
                }
                return 0;
        }
